/*
 * Copyright (c) Huawei Device Co., Ltd. 2023. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef CHANNEL_IMPL_H
#define CHANNEL_IMPL_H
#include <mutex>
#include "channel_stub.h"
#include "loghelper.h"
#include "session_impl.h"

namespace OHOS {
namespace SE {

class ChannelImpl final : public OMAPI::ChannelStub,
    public std::enable_shared_from_this<ChannelImpl> {
public:
    /**
     * @brief Constructor of ChannelImpl
     * @param agent The hdf agent used to access the secure element hardware.
     * @param isBasic The Channel is basic or logical.
     * @param channelNumber The channel number of this channel.
     */
    ChannelImpl(std::weak_ptr<SecureElementAgent> agent, bool isBasic, uint8_t channelNumber,
     const std::string &selectResponse);

    ~ChannelImpl();
    /**
     * @brief Closes this channel to the SE. If the method is called when the channel is already closed,
     * this method SHALL be ignored.
     * @return The status code for function calling.
     */
    ErrorCode Close(void) override;
    /**
     * @brief Tells if this channel is closed.
     * @param isClosed - True if the channel is closed, false otherwise.
     * @return The status code for function calling.
     */
    ErrorCode IsClosed(bool &isClosed) override;
    /**
     * @brief Returns a Bool indicating whether this channel is the basic channel.
     * @param isBasicChannel - True if this channel is a basic channel. False if this channel is a logical channel.
     * @return The status code for function calling.
     */
    ErrorCode IsBasicChannel(bool &isBasicChannel) override;
    /**
     * @brief Returns the data as received from the application select command, including the status word received at
     * applet selection.
     * @param selectResponse - The returned byte array contains the data bytes in the following order:
     *          [<first data byte>, …, <last data byte>, <sw1>, <sw2>]
     * @return The status code for function calling.
     */
    ErrorCode GetSelectResponse(std::string &selectResponse) override;
    /**
     * @brief Transmit an APDU command (as per ISO/IEC 7816) to the SE.
     * @param command - The APDU command to be transmitted, as a byte array.
     * @param response - The response received, as a byte array.
     * The returned byte array contains the data bytes in the following order:
     * {<first data byte>, …, <last data byte>, <sw1>, <sw2>}.
     * @return The status code for function calling.
     */
    ErrorCode Transmit(const std::string &command, std::string& response) override;
    /**
     * @brief Performs a selection of the next applet on this channel that matches to the partial AID specified in the
     * openBasicChannel() or openLogicalChannel() method.
     * @param selectStatus - True, a new applet was successfully selected on this channel.
     * return false, if no further applet exists with matches to the partial AID, and the applet already selected stays
     * selected.
     * @return The status code for function calling.
     */
    ErrorCode SelectNext(bool &selectStatus) override;

    /**
     * @brief Get the channel number of this channel.
     * @param channelNumber - The channel number.
     * @return The status code for function calling.
     */
    ErrorCode GetChannelNumber(uint8_t &channelNumber) override;

    /**
     * @brief Set the channel wheather closed
     * @param channelState - The channel state.
     * @return The status code for function calling.
     */
    ErrorCode SetChannelState(bool channelState);
private:
    // hdf agent used to access the secure element hardware.
    std::weak_ptr<SecureElementAgent> boundHdfAgent_{};

    // the mutex used to access secure element hdf.
    std::mutex mutex_{};

    // this channel is basic or not
    bool isBasicChannel_ = false;

    // the channel number
    uint8_t channelNumber_ = 0;

    // this channel is closed or not.
    bool isChannelClosed_ = false;

    // channel response.
    std::string selectResponse_{};
};
}  // namespace SE
}  // namespace OHOS
#endif // !CHANNEL_IMPL_H
